home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / c / c-tools-.000 / c-tools- / c-tools-0.4 / lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-13  |  8.4 KB  |  455 lines

  1. /* lex.c -- C-tools lexical analyzer.
  2.    Copyright (C) 1995 Sandro Sigala  */
  3.  
  4. /* $Id: lex.c,v 1.11 1995/08/08 12:29:23 sandro Exp $ */
  5.  
  6. /* This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.
  10.  
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20.  
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include "lex.h"
  27. #include "misc.h"
  28.  
  29. extern FILE *input_file;
  30.  
  31. int lex_lineno = 1;
  32. char *lex_token_buffer;
  33.  
  34. int lex_return_white_spaces = 0;
  35. int lex_return_directives = 1;
  36.  
  37. #define MAX_LEXER_BUFFER 64
  38.  
  39. /* max allowed token size */
  40. static int maxtoken;
  41.  
  42. /* char buffer */
  43. static char lexbuf[MAX_LEXER_BUFFER];
  44.  
  45. /* char buffer index */
  46. static int lexbufidx = 0;
  47.  
  48. #define lexgetc() \
  49.     (lexbufidx ? lexbuf[--lexbufidx] : getc (input_file))
  50.  
  51. #define lexungetc(c) \
  52.     lexbuf[lexbufidx++] = c
  53.  
  54. void init_lex (void);
  55. void done_lex (void);
  56. int gettoken (void);
  57. void ungettoken (void);
  58.  
  59. int gettoken (void);
  60. static char *extend_token_buffer (char *);
  61. static int is_reserved_word (char *);
  62.  
  63. void
  64. init_lex (void)
  65. {
  66.     maxtoken = 40;
  67.     lex_token_buffer = (char *) xmalloc (maxtoken + 1);
  68. }
  69.  
  70. void
  71. done_lex (void)
  72. {
  73.     free (lex_token_buffer);
  74. }
  75.  
  76. static char *
  77. extend_token_buffer (char *p)
  78. {
  79.     int offset = p - lex_token_buffer;
  80.  
  81.     maxtoken = maxtoken * 2 + 10;
  82.     lex_token_buffer = (char *) xrealloc (lex_token_buffer, maxtoken + 2);
  83.  
  84.     return lex_token_buffer + offset;
  85. }
  86.  
  87. static int
  88. is_reserved_word (char *word)
  89. {
  90.     static struct { char *w; int t; } wordlist[] =
  91.     {
  92.     {"auto", KW_AUTO},        {"break", KW_BREAK},
  93.     {"case", KW_CASE},        {"char", KW_CHAR},
  94.     {"const", KW_CONST},        {"continue", KW_CONTINUE},
  95.     {"default", KW_DEFAULT},    {"do", KW_DO},
  96.     {"double", KW_DOUBLE},        {"else", KW_ELSE},
  97.     {"enum", KW_ENUM},        {"extern", KW_EXTERN},
  98.     {"float", KW_FLOAT},        {"for", KW_FOR},
  99.     {"goto", KW_GOTO},        {"if", KW_IF},
  100.     {"int", KW_INT},        {"long", KW_LONG},
  101.     {"register", KW_REGISTER},    {"return", KW_RETURN},
  102.     {"short", KW_SHORT},        {"signed", KW_SIGNED},
  103.     {"sizeof", KW_SIZEOF},        {"static", KW_STATIC},
  104.     {"struct", KW_STRUCT},        {"switch", KW_SWITCH},
  105.     {"typedef", KW_TYPEDEF},    {"union", KW_UNION},
  106.     {"unsigned", KW_UNSIGNED},    {"void", KW_VOID},
  107.     {"volatile", KW_VOLATILE},    {"while", KW_WHILE},
  108.     {0, 0}
  109.     };
  110.     int i = 0, t;
  111.  
  112.     while ((t = wordlist[i].t) != 0)
  113.     if (strcmp (wordlist[i++].w, word) == 0)
  114.         return t;
  115.  
  116.     return 0;
  117. }
  118.  
  119. int
  120. gettoken (void)
  121. {
  122.     int c, c1, c2, i;
  123.     char *p;
  124.  
  125.     lex_token_buffer[0] = '\0';
  126.  
  127.     c = lexgetc ();
  128.  
  129.     if (c == EOF)
  130.     return EOF;
  131.  
  132.     switch (c)
  133.     {
  134.     case '\n':
  135.     lex_lineno++;
  136.  
  137.     case ' ':
  138.     case '\011':        /* horizontal tab */
  139.     case '\013':        /* vertical tab */
  140.     case '\014':        /* form feed */
  141.     case '\015':        /* carriage return */
  142.     if (lex_return_white_spaces == 1)
  143.         return c;
  144.     else
  145.         return (gettoken ());
  146.     break;
  147.  
  148.     case '#':
  149.     if (lex_return_directives)
  150.     {
  151.         p = lex_token_buffer;
  152.  
  153.         *p++ = c;
  154.  
  155.         while ((c1 = lexgetc ()) != EOF && c1 != '\n')
  156.         {
  157.         if (p >= lex_token_buffer + maxtoken)
  158.             p = extend_token_buffer (p);
  159.         *p++ = c1;
  160.         }
  161.         *p++ = c1;
  162.         *p = 0;
  163.         return DIRECTIVE;
  164.     }
  165.     else
  166.         return '#';
  167.  
  168.     case 'A': case 'B': case 'C': case 'D': case 'E':
  169.     case 'F': case 'G': case 'H': case 'I': case 'J':
  170.     case 'K': case 'L': case 'M': case 'N': case 'O':
  171.     case 'P': case 'Q': case 'R': case 'S': case 'T':
  172.     case 'U': case 'V': case 'W': case 'X': case 'Y':
  173.     case 'Z':
  174.     case 'a': case 'b': case 'c': case 'd': case 'e':
  175.     case 'f': case 'g': case 'h': case 'i': case 'j':
  176.     case 'k': case 'l': case 'm': case 'n': case 'o':
  177.     case 'p': case 'q': case 'r': case 's': case 't':
  178.     case 'u': case 'v': case 'w': case 'x': case 'y':
  179.     case 'z':
  180.     case '_':
  181.     p = lex_token_buffer;
  182.     while (isalnum (c) || c == '_')
  183.     {
  184.         if (p >= lex_token_buffer + maxtoken)
  185.         p = extend_token_buffer (p);
  186.  
  187.         *p++ = c;
  188.         c = lexgetc ();
  189.     }
  190.     lexungetc (c);
  191.  
  192.     *p = 0;
  193.  
  194.     if ((i = is_reserved_word (lex_token_buffer)) != 0)
  195.         return i;
  196.     else
  197.         return IDENTIFIER;
  198.  
  199.     case '0':
  200.     case '1': case '2': case '3':
  201.     case '4': case '5': case '6':
  202.     case '7': case '8': case '9':
  203.     {
  204.     int firstch = c, start = 0;
  205.     p = lex_token_buffer;
  206.     while (isdigit (c))
  207.     {
  208.         if (p >= lex_token_buffer + maxtoken)
  209.         p = extend_token_buffer (p);
  210.  
  211.         *p++ = c;
  212.         c = lexgetc ();
  213.  
  214.         if (!start && firstch == '0')
  215.         if (c == 'x')
  216.         {
  217.             *p++ = c;
  218.             while (isxdigit (c1 = lexgetc ()))
  219.             {
  220.             if (p >= lex_token_buffer + maxtoken)
  221.                 p = extend_token_buffer (p);
  222.             *p++ = c1;
  223.             }
  224.             *p = '\0';
  225.             lexungetc (c1);
  226.             return NUMBER;
  227.         }
  228.         start = 1;
  229.     }
  230.     lexungetc (c);
  231.  
  232.     *p = '\0';
  233.  
  234.     return NUMBER;
  235.     }
  236.  
  237.     case '+':
  238.     if ((c1 = lexgetc ()) == '+')
  239.         return TK_INCREMENT;
  240.     else if (c1 == '=')
  241.         return TK_ADD_ASSIGN;
  242.     else
  243.     {
  244.         lexungetc (c1);
  245.         return '+';
  246.     }
  247.  
  248.     case '-':
  249.     if ((c1 = lexgetc ()) == '-')
  250.         return TK_DECREMENT;
  251.     else if (c1 == '=')
  252.         return TK_SUB_ASSIGN;
  253.     else if (c1 == '>')
  254.         return TK_PTR_OP;
  255.     else
  256.     {
  257.         lexungetc (c1);
  258.         return '-';
  259.     }
  260.  
  261.     case '*':
  262.     if ((c1 = lexgetc ()) == '=')
  263.         return TK_MUL_ASSIGN;
  264.     else
  265.     {
  266.         lexungetc (c1);
  267.         return '*';
  268.     }
  269.  
  270.     case '/':
  271.     if ((c1 = lexgetc ()) == '=')
  272.         return TK_DIV_ASSIGN;
  273.     else
  274.     {
  275.         if (c1 == '*')
  276.         {
  277.         p = lex_token_buffer;
  278.         *p++ = '/';
  279.         *p++ = '*';
  280.         while ((c1 = lexgetc ()) != EOF)
  281.         {
  282.             if (p >= lex_token_buffer + maxtoken)
  283.             p = extend_token_buffer (p);
  284.  
  285.             *p++ = c1;
  286.  
  287.             if (c1 == '*')
  288.             if ((c2 = lexgetc ()) == '/')
  289.             {
  290.                 *p++ = c2;
  291.                 *p = '\0';
  292.                 return COMMENT;
  293.             }
  294.             else
  295.                 *p++ = c2;
  296.         }
  297.         *p = '\0';
  298.         }
  299.         lexungetc (c1);
  300.         return '/';
  301.     }
  302.  
  303.     case '%':
  304.         if ((c1 = lexgetc ()) == '=')
  305.         return TK_MOD_ASSIGN;
  306.         else
  307.         {
  308.         lexungetc (c1);
  309.         return '%';
  310.         }
  311.  
  312.     case '!':
  313.         if ((c1 = lexgetc ()) == '=')
  314.         return TK_NE_OP;
  315.         else
  316.         {
  317.         lexungetc (c1);
  318.         return '!';
  319.         }
  320.  
  321.     case '=':
  322.         if ((c1 = lexgetc ()) == '=')
  323.         return TK_EQ_OP;
  324.         else
  325.         {
  326.         lexungetc (c1);
  327.         return '=';
  328.         }
  329.  
  330.     case '&':
  331.         if ((c1 = lexgetc ()) == '=')
  332.         return TK_AND_ASSIGN;
  333.         else if (c1 == '&')
  334.         return TK_AND_OP;
  335.         else
  336.         {
  337.         lexungetc (c1);
  338.         return '&';
  339.         }
  340.  
  341.     case '|':
  342.         if ((c1 = lexgetc ()) == '=')
  343.         return TK_OR_ASSIGN;
  344.         else if (c1 == '|')
  345.         return TK_OR_OP;
  346.         else
  347.         {
  348.         lexungetc (c1);
  349.         return '|';
  350.         }
  351.  
  352.     case '^':
  353.         if ((c1 = lexgetc ()) == '=')
  354.         return TK_XOR_ASSIGN;
  355.         else
  356.         {
  357.         lexungetc (c1);
  358.         return '^';
  359.         }
  360.  
  361.     case '>':
  362.         if ((c1 = lexgetc ()) == '=')
  363.         return TK_GE_OP;
  364.         else if (c1 == '>')
  365.         if ((c2 = lexgetc ()) == '=')
  366.             return TK_LEFT_ASSIGN;
  367.         else
  368.         {
  369.             lexungetc (c2);
  370.             return TK_LEFT_OP;
  371.         }
  372.         else
  373.         {
  374.         lexungetc (c1);
  375.         return '>';
  376.         }
  377.  
  378.     case '<':
  379.         if ((c1 = lexgetc ()) == '=')
  380.         return TK_LE_OP;
  381.         else if (c1 == '<')
  382.         if ((c2 = lexgetc ()) == '=')
  383.             return TK_RIGHT_ASSIGN;
  384.         else
  385.         {
  386.             lexungetc (c2);
  387.             return TK_RIGHT_OP;
  388.         }
  389.         else
  390.         {
  391.         lexungetc (c1);
  392.         return '<';
  393.         }
  394.  
  395.     case '.':
  396.         if ((c1 = lexgetc ()) == '.')
  397.         if ((c2 = lexgetc ()) == '.')
  398.             return TK_ELLIPSIS;
  399.         else
  400.         {
  401.             lexungetc (c2);
  402.             lexungetc (c1);
  403.             return '.';
  404.         }
  405.         else
  406.         {
  407.         lexungetc (c1);
  408.         return '.';
  409.         }
  410.  
  411.     case '"':
  412.         p = lex_token_buffer;
  413.         *p++ = '"';
  414.         while ((c1 = lexgetc ()) != EOF && c1 != '"')
  415.         {
  416.         if (p >= lex_token_buffer + maxtoken)
  417.             p = extend_token_buffer (p);
  418.         *p++ = c1;
  419.  
  420.         if (c1 == '\\')
  421.             *p++ = lexgetc ();
  422.         }
  423.  
  424.         *p++ = '"';
  425.  
  426.         *p = 0;
  427.  
  428.         return STRING;
  429.  
  430.     case '\'':
  431.         p = lex_token_buffer;
  432.         *p++ = '\'';
  433.         while ((c1 = lexgetc ()) != EOF && c1 != '\'')
  434.         {
  435.         if (p >= lex_token_buffer + maxtoken)
  436.             p = extend_token_buffer (p);
  437.         *p++ = c1;
  438.  
  439.         if (c1 == '\\')
  440.             *p++ = lexgetc ();
  441.         }
  442.  
  443.         *p++ = '\'';
  444.  
  445.         *p = 0;
  446.  
  447.         return CHARACTER;
  448.  
  449.     default:
  450.         return c;
  451.     }
  452. }
  453.  
  454. /* lex.c ends here */
  455.